import os
import logging
import sys
from datetime import datetime
from typing import Optional, Dict, Any
import json
import traceback

class RequestLogger:
    """
    请求日志记录器，为每个请求创建唯一的日志文件
    """
    
    def __init__(self, log_dir: str = "logs"):
        """
        初始化日志记录器
        
        参数:
            log_dir: 日志存储目录
        """
        self.log_dir = log_dir
        self.loggers: Dict[str, logging.Logger] = {}
        self.current_request_id: Optional[str] = None
        
        # 确保日志目录存在
        os.makedirs(log_dir, exist_ok=True)
        
    def start_request(self, prefix: str = "request") -> str:
        """
        开始一个新的请求日志记录，返回请求ID
        
        参数:
            prefix: 日志文件名前缀
            
        返回:
            请求ID，格式为 {prefix}_{timestamp}
        """
        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S_%f")
        request_id = f"{prefix}_{timestamp}"
        self.current_request_id = request_id
        
        # 创建日志文件
        log_file = os.path.join(self.log_dir, f"{request_id}.log")
        
        # 配置logger
        logger = logging.getLogger(request_id)
        logger.setLevel(logging.DEBUG)
        
        # 如果logger已经有handlers，先清除
        if logger.handlers:
            logger.handlers.clear()
        
        # 添加文件处理器
        file_handler = logging.FileHandler(log_file, encoding='utf-8')
        file_handler.setLevel(logging.DEBUG)
        
        # 设置格式
        formatter = logging.Formatter('%(asctime)s [%(levelname)s] %(message)s')
        file_handler.setFormatter(formatter)
        
        logger.addHandler(file_handler)
        
        # 可选：添加控制台处理器（如果需要同时输出到控制台）
        console_handler = logging.StreamHandler(sys.stdout)
        console_handler.setLevel(logging.DEBUG)
        console_handler.setFormatter(formatter)
        logger.addHandler(console_handler)
        
        # 存储logger
        self.loggers[request_id] = logger
        
        # 记录请求开始
        logger.info(f"=== 开始新请求: {request_id} ===")
        
        return request_id
    
    def end_request(self, request_id: Optional[str] = None) -> None:
        """
        结束请求日志记录
        
        参数:
            request_id: 请求ID，如果为None则使用当前请求ID
        """
        if request_id is None:
            request_id = self.current_request_id
        
        if request_id and request_id in self.loggers:
            logger = self.loggers[request_id]
            logger.info(f"=== 请求结束: {request_id} ===")
            
            # 关闭并移除handlers
            for handler in logger.handlers[:]:
                handler.close()
                logger.removeHandler(handler)
                
            # 从字典中移除
            del self.loggers[request_id]
            
            if request_id == self.current_request_id:
                self.current_request_id = None
                
    def get_logger(self, request_id: Optional[str] = None) -> Optional[logging.Logger]:
        """
        获取指定请求ID的logger
        
        参数:
            request_id: 请求ID，如果为None则使用当前请求ID
            
        返回:
            Logger对象，如果找不到则返回None
        """
        if request_id is None:
            request_id = self.current_request_id
            
        if request_id and request_id in self.loggers:
            return self.loggers[request_id]
        return None
    
    def log(self, 
            message: str, 
            level: str = "info", 
            request_id: Optional[str] = None,
            data: Any = None) -> None:
        """
        记录日志
        
        参数:
            message: 日志消息
            level: 日志级别 (debug, info, warning, error, critical)
            request_id: 请求ID，如果为None则使用当前请求ID
            data: 要记录的额外数据，会被转换为JSON字符串
        """
        logger = self.get_logger(request_id)
        if not logger:
            return
            
        # 处理额外数据
        log_message = message
        if data is not None:
            try:
                if isinstance(data, (dict, list, tuple, str, int, float, bool)) or data is None:
                    data_str = json.dumps(data, ensure_ascii=False, indent=2)
                    log_message = f"{message}\n{data_str}"
                else:
                    log_message = f"{message}\n{str(data)}"
            except Exception as e:
                log_message = f"{message}\n无法序列化数据: {str(e)}"
        
        # 根据级别记录日志
        level = level.lower()
        if level == "debug":
            logger.debug(log_message)
        elif level == "info":
            logger.info(log_message)
        elif level == "warning":
            logger.warning(log_message)
        elif level == "error":
            logger.error(log_message)
        elif level == "critical":
            logger.critical(log_message)
        else:
            logger.info(log_message)  # 默认用info级别
    
    def exception(self, message: str, request_id: Optional[str] = None) -> None:
        """
        记录异常信息，包括堆栈跟踪
        
        参数:
            message: 异常消息
            request_id: 请求ID，如果为None则使用当前请求ID
        """
        logger = self.get_logger(request_id)
        if not logger:
            return
            
        # 获取当前异常的堆栈跟踪
        exc_info = sys.exc_info()
        if exc_info[0] is not None:  # 如果有异常
            exception_text = "".join(traceback.format_exception(*exc_info))
            logger.error(f"{message}\n{exception_text}")
        else:
            logger.error(message)

# 全局实例
request_logger = RequestLogger() 